package com.github.caijh.mall.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import javax.inject.Inject;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.caijh.framework.core.exception.BizException;
import com.github.caijh.framework.data.redis.Redis;
import com.github.caijh.mall.common.MessageConstants;
import com.github.caijh.mall.common.PageParams;
import com.github.caijh.mall.config.properties.AppProperties;
import com.github.caijh.mall.constants.Constants;
import com.github.caijh.mall.exception.CrmebException;
import com.github.caijh.mall.express.vo.ExpressSheetVo;
import com.github.caijh.mall.system.dao.SystemConfigDao;
import com.github.caijh.mall.system.model.SystemConfig;
import com.github.caijh.mall.system.request.SystemFormCheckReqBody;
import com.github.caijh.mall.system.request.SystemFormItemCheckRequest;
import com.github.caijh.mall.system.service.SystemAttachmentService;
import com.github.caijh.mall.system.service.SystemConfigService;
import com.github.caijh.mall.system.service.SystemFormTempService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import static com.github.pagehelper.page.PageMethod.startPage;

@Service
public class SystemConfigServiceImpl extends ServiceImpl<SystemConfigDao, SystemConfig> implements SystemConfigService {

    @Resource
    private SystemConfigDao dao;

    @Autowired
    private SystemFormTempService systemFormTempService;

    @Autowired
    private SystemAttachmentService systemAttachmentService;

    @Inject
    private AppProperties appProperties;

    @Inject
    private Redis redis;

    /**
     * 搜索列表
     *
     * @param pageParams PageParams 分页参数
     * @return List<SystemConfig>
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public List<SystemConfig> getList(PageParams pageParams) {
        startPage(pageParams.getPage(), pageParams.getLimit());
        LambdaQueryWrapper<SystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.select(
                SystemConfig::getId,
                SystemConfig::getTitle,
                SystemConfig::getName,
                SystemConfig::getValue,
                SystemConfig::getStatus

        );
        lambdaQueryWrapper.eq(SystemConfig::getStatus, false);
        return dao.selectList(lambdaQueryWrapper);
    }

    /**
     * 根据menu name 获取 value
     *
     * @param name menu name
     * @return String
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public String getValueByKey(String name) {
        return get(name);
    }


    /**
     * 同时获取多个配置
     *
     * @param keys 多个配置key
     * @return List<String>
     */
    @Override
    public List<String> getValuesByKes(List<String> keys) {
        List<String> result = new ArrayList<>();
        for (String key : keys) {
            result.add(getValueByKey(key));
        }
        return result;
    }

    /**
     * 根据 name 获取 value 找不到抛异常
     *
     * @param name menu name
     * @return String
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public String getValueByKeyException(String name) {
        String value = get(name);
        if (null == value) {
            throw BizException.of(MessageConstants.CONFIG_NAME_NOT_FOUND, name);
        }

        return value;
    }

    /**
     * 整体保存表单数据
     *
     * @param systemFormCheckReqBody SystemFormCheckRequest 数据保存
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-04-13
     */
    @Override
    public boolean saveForm(SystemFormCheckReqBody systemFormCheckReqBody) {
        //检测form表单，并且返回需要添加的数据
        systemFormTempService.checkForm(systemFormCheckReqBody);

        List<SystemConfig> systemConfigList = new ArrayList<>();

        //批量添加
        for (SystemFormItemCheckRequest systemFormItemCheckRequest : systemFormCheckReqBody.getFields()) {
            SystemConfig systemConfig = new SystemConfig();
            systemConfig.setName(systemFormItemCheckRequest.getName());

            String value = systemAttachmentService.clearPrefix(systemFormItemCheckRequest.getValue());
            if (StringUtils.isBlank(value)) {
                //去掉图片域名之后没有数据则说明当前数据就是图片域名
                value = systemFormItemCheckRequest.getValue();
            }
            systemConfig.setValue(value);
            systemConfig.setFormId(systemFormCheckReqBody.getId());
            systemConfig.setTitle(systemFormItemCheckRequest.getTitle());
            systemConfigList.add(systemConfig);
        }

        //修改之前的数据
        updateStatusByFormId(systemFormCheckReqBody.getId());

        saveBatch(systemConfigList);

        //删除之前隐藏的数据
        deleteStatusByFormId(systemFormCheckReqBody.getId());
        systemConfigList.forEach(e -> e.setStatus(true));

        sync(systemConfigList);

        return true;
    }


    /**
     * updateStatusByGroupId
     *
     * @param formId Integer formId
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    private void updateStatusByFormId(Integer formId) {
        LambdaQueryWrapper<SystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SystemConfig::getFormId, formId).eq(SystemConfig::getStatus, false);

        SystemConfig systemConfig = new SystemConfig();
        systemConfig.setStatus(true);
        update(systemConfig, lambdaQueryWrapper);

    }

    /**
     * deleteStatusByGroupId
     *
     * @param formId Integer formId
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    private void deleteStatusByFormId(Integer formId) {
        LambdaQueryWrapper<SystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //删除已经隐藏的数据
        lambdaQueryWrapper.eq(SystemConfig::getFormId, formId).eq(SystemConfig::getStatus, true);
        List<SystemConfig> systemConfigList = dao.selectList(lambdaQueryWrapper);
        dao.delete(lambdaQueryWrapper);
        sync(systemConfigList);
    }


    /**
     * 保存或更新配置数据
     *
     * @param name  菜单名称
     * @param value 菜单值
     * @return boolean
     */
    @Override
    public boolean updateOrSaveValueByName(String name, String value) {
        value = systemAttachmentService.clearPrefix(value);

        LambdaQueryWrapper<SystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SystemConfig::getName, name);
        List<SystemConfig> systemConfigs = dao.selectList(lambdaQueryWrapper);
        if (systemConfigs.size() >= 2) {
            throw new CrmebException("配置名称存在多个请检查配置 eb_system_config 重复数据：" + name + "条数：" + systemConfigs.size());
        }
        SystemConfig systemConfig;
        if (systemConfigs.isEmpty()) {
            systemConfig = new SystemConfig().setName(name).setValue(value);
            save(systemConfig);
        } else {
            systemConfig = systemConfigs.get(0);
            systemConfig.setValue(value);
            saveOrUpdate(systemConfig);
        }
        sync(Collections.singletonList(systemConfig));

        return true;
    }


    /**
     * 根据formId查询数据
     *
     * @param formId Integer id
     * @return HashMap<String, String>
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public Map<String, String> info(Integer formId) {
        LambdaQueryWrapper<SystemConfig> wrapper = Wrappers.<SystemConfig>lambdaQuery()
                .eq(SystemConfig::getFormId, formId);
        List<SystemConfig> systemConfigList = dao.selectList(wrapper);
        if (systemConfigList.isEmpty()) {
            return null;
        }
        Map<String, String> map = systemConfigList.stream().collect(Collectors.toMap(SystemConfig::getName, SystemConfig::getValue));
        map.put("id", formId.toString());
        return map;
    }

    /**
     * 根据name查询数据
     *
     * @param name name
     * @return boolean
     * @author Mr.Zhang
     * @since 2020-04-16
     */
    @Override
    public boolean checkName(String name) {
        String value = get(name);
        return value == null;
    }

    /**
     * 获取系统电子面单信息
     */
    @Override
    public ExpressSheetVo getExpressSheet() {
        String exportId = get("config_export_id");
        if (StrUtil.isBlank(exportId)) {
            throw new CrmebException("请先开通电子面单");
        }
        String exportTempId = get("config_export_temp_id");
        if (StrUtil.isBlank(exportTempId)) {
            throw new CrmebException("请先开通电子面单");
        }
        String exportCom = get("config_export_com");
        if (StrUtil.isBlank(exportCom)) {
            throw new CrmebException("请先开通电子面单");
        }
        String exportToName = get("config_export_to_name");
        if (StrUtil.isBlank(exportToName)) {
            throw new CrmebException("请先开通电子面单");
        }
        String exportToTel = get("config_export_to_tel");
        if (StrUtil.isBlank(exportToTel)) {
            throw new CrmebException("请先开通电子面单");
        }
        String exportToAddress = get("config_export_to_address");
        if (StrUtil.isBlank(exportToAddress)) {
            throw new CrmebException("请先开通电子面单");
        }
        String exportSiid = get("config_export_siid");
        if (StrUtil.isBlank(exportSiid)) {
            throw new CrmebException("请先开通电子面单");
        }
        return new ExpressSheetVo(Integer.valueOf(exportId), exportCom, exportTempId, exportToName, exportToTel, exportToAddress, exportSiid);
    }

    /**
     * 获取面单默认配置信息
     *
     * @return ExpressSheetVo
     */
    @Override
    public ExpressSheetVo getDeliveryInfo() {
        String exportId = get("config_export_id");
        String exportTempId = get("config_export_temp_id");
        String exportCom = get("config_export_com");
        String exportToName = get("config_export_to_name");
        String exportToTel = get("config_export_to_tel");
        String exportToAddress = get("config_export_to_address");
        String exportSiid = get("config_export_siid");
        String exportOpen = get("config_export_open");
        return new ExpressSheetVo(Integer.valueOf(exportId), exportCom, exportTempId, exportToName, exportToTel, exportToAddress, exportSiid, Integer
                .valueOf(exportOpen));
    }


    private void sync(List<SystemConfig> systemConfigList) {
        for (SystemConfig systemConfig : systemConfigList) {
            if (Boolean.TRUE.equals(systemConfig.getStatus())) {
                redis.getRedisTemplate().opsForHash().delete(Constants.CONFIG_LIST, systemConfig.getName());
            } else {
                redis.getRedisTemplate().opsForHash().put(Constants.CONFIG_LIST, systemConfig.getName(), systemConfig);
            }
        }
    }

    private String get(String name) {
        SystemConfig config = redis.getRedisTemplate().<String, SystemConfig>opsForHash().get(Constants.CONFIG_LIST, name);
        if (config != null) {
            return config.getValue();
        }

        LambdaQueryWrapper<SystemConfig> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SystemConfig::getStatus, false).eq(SystemConfig::getName, name);
        config = dao.selectOne(lambdaQueryWrapper);
        if (config == null) {
            config = new SystemConfig();
        }
        redis.getRedisTemplate().opsForHash().put(Constants.CONFIG_LIST, name, config);
        return config.getValue();
    }

}

